package com.file;

import java.io.*;
import java.sql.Connection;
import java.util.Iterator;
import java.util.List;

import javax.servlet.ServletException;
import javax.servlet.http.*;

import org.apache.commons.fileupload.*;
import org.apache.commons.fileupload.servlet.ServletFileUpload;

import com.gdit.zax.dao.UpLoadDao;
import com.gdit.zax.entitys.UpLoad;
import com.gdit.zax.factory.DAOFactory;
import com.gdit.zax.thread.DeleteFileThread;
import com.gdit.zax.utils.DBUtil;
import com.gdit.zax.utils.FromRequest;
import com.gdit.zax.utils.LogUtil;
import com.gdit.zax.utils.TextUtil;
import com.gdit.zax.utils.WebUpload;
import com.gdit.zax.utils.webUtil;

/**
 * 上传文件Servlet
 * 
 * @author 毛正吉
 * 
 */
public class UploadServlet extends HttpServlet {
	private String uploadpath;//保存的目录
	
	@Override
	public void init() throws ServletException {
		System.out.println("UploadServlet init!!!");
		uploadpath = getServletContext().getRealPath("/") + "upload";
		new File(uploadpath).mkdirs();
		//删除旧文件
		File[] files = new File(uploadpath).listFiles();
		for (int i = 0; i < files.length; i++) {
			LogUtil.print("删除临时文件:" + files[i].getAbsolutePath());
			files[i].delete();
		}
		super.init();
	}

	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws IOException, ServletException {
		// 创建HttpSession对象
		HttpSession session = request.getSession();
		// 如果请求中c的值为status
		if ("status".equals(request.getParameter("c"))) {
			doStatus(session, response);// 调用doStatus方法
		} else {// 否则，调用doFileUpload方法
			doFileUpload(session, request, response);
		}
	}

	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws IOException, ServletException {
		doPost(request, response);
	}

	/**
	 * 文件上传
	 * 
	 * @param session
	 * @param request
	 * @param response
	 * @throws IOException
	 */
	private void doFileUpload(HttpSession session, HttpServletRequest request,
			HttpServletResponse response)  { 
		String errormsg = "Could not process uploaded file. Please see log for details.";
		String tempName = System.currentTimeMillis() + "";
		String fileName = tempName;
		String flag = null;
		
		try {
			// 创建UploadListener对象
			UploadListener listener = new UploadListener(request
					.getContentLength());
			listener.start();// 启动监听状态
			// 将监听器对象的状态保存在Session中
			session.setAttribute("FILE_UPLOAD_STATS", listener
					.getFileUploadStats());
			// 创建MonitoredDiskFileItemFactory对象
			FileItemFactory factory = new MonitoredDiskFileItemFactory(listener);
			// 通过该工厂对象创建ServletFileUpload对象
			ServletFileUpload upload = new ServletFileUpload(factory);
			// 将转化请求保存到list对象中
			List items = upload.parseRequest(request);
			// 停止使用监听器
			listener.done();
			
			
			boolean hasError = false;
			// 循环list中的对象
			for (Iterator i = items.iterator(); i.hasNext();) {
				FileItem fileItem = (FileItem) i.next();
				
				if (!fileItem.isFormField()) {// 如果该FileItem不是表单域
					//处理文件
					
					//后缀名
					String exname = WebUpload.getExtensionName(fileItem.getName());
					tempName =  tempName + "." +  exname;
//					if (exname==null || exname.equals("")) {
//						hasError = true;
//						errormsg = "The file type error";
//					} else if (!(exname.equals("avi") || exname.equals("mp4"))) {
//						hasError = true;
//						errormsg = "The file type error(only avi or mp4)";
//					}
					
					fileName = fileItem.getName().substring(fileItem.getName().lastIndexOf("\\") + 1);
					new DeleteFileThread(new File(uploadpath, tempName),1000*60*60*(long)24).start();//1天后删除
					
					processUploadedFile(fileItem,tempName);// 调用processUploadedFile方法,将数据保存到文件中
					try {
						fileItem.delete();// 内存中删除该数据流
					} catch (Exception e) {
					}
				} else {
					System.out.println(fileItem.getName() + ">>" + fileItem.getFieldName() + " == " + fileItem.getString());
					String key = fileItem.getFieldName();
					if ("flag".equals(key)){
						flag = fileItem.getString();
					}
				}
			}
			
			//加入数据库
			UpLoad info = new UpLoad();
			info.setFlag(flag);
			info.setFilename(fileName);
			info.setFilepath("upload" +  File.separator+ tempName);
			Connection  conn = DBUtil.getConnection();
			if (conn!=null) {
				UpLoadDao udao = DAOFactory.init(conn, request, response).getUploadDao();
				if (!udao.addUploda(info)){
					new File(uploadpath, tempName).delete();
				}
			}

			
			
			if (!hasError) {// 如果没有出现错误
				sendCompleteResponse(response, null);// 调用sendCompleteResponse方法
			} else {
				sendCompleteResponse(response,errormsg);
			}
		} catch (Exception e) {
			sendCompleteResponse(response, e.getMessage());
		}
	}

	/**
	 * 文件上传过程处理
	 * 
	 * @param item
	 * @throws IOException 
	 */
	public void processUploadedFile(FileItem item,String fileName) throws IOException {
		// 获得上传文件的文件名
//		String fileName = item.getName().substring(item.getName().lastIndexOf("\\") + 1);
//		String fileName = System.currentTimeMillis() +"." + WebUpload.getExtensionName(item.getName());
		
		// 创建File对象,将上传的文件保存到C:\\upload文件夹下
		File fDir = new File(uploadpath);
		if (!fDir.exists()) {
			fDir.mkdirs();
		}
		File file = new File(fDir, fileName);
		InputStream in;
		
		in = item.getInputStream();// 获得输入数据流文件
		// 将该数据流写入到指定文件中
		FileOutputStream out = new FileOutputStream(file);
		byte[] buffer = new byte[4096];
		int bytes_read;
		while ((bytes_read = in.read(buffer)) != -1) {
			out.write(buffer, 0, bytes_read);
		}
		if (in != null)
				in.close();
		if (out != null)
				out.close();
				
	}

	private void doStatus(HttpSession session, HttpServletResponse response)
			throws IOException {
		//设置该响应不在缓存中读取
		response.addHeader("Expires", "0");
		response.addHeader("Cache-Control",
				"no-store, no-cache, must-revalidate");
		response.addHeader("Cache-Control", "post-check=0, pre-check=0");
		response.addHeader("Pragma", "no-cache");
		// 获得保存在Session中的状态信息
		UploadListener.FileUploadStats fileUploadStats = (UploadListener.FileUploadStats) session
				.getAttribute("FILE_UPLOAD_STATS");
		if (fileUploadStats != null) {
			long bytesProcessed = fileUploadStats.getBytesRead();// 获得已经上传的数据大小
			long sizeTotal = fileUploadStats.getTotalSize();// 获得上传文件的总大小
			// 计算上传完成的百分比
			long percentComplete = (long) Math
					.floor(((double) bytesProcessed / (double) sizeTotal) * 100.0);
			// 获得上传已用的时间
			long timeInSeconds = fileUploadStats.getElapsedTimeInSeconds();
			// 计算平均上传速率
			double uploadRate = bytesProcessed / (timeInSeconds + 0.00001);
			// 计算总共所需时间
			double estimatedRuntime = sizeTotal / (uploadRate + 0.00001);
			// 将上传状态返回给客户端
			response.getWriter().println("<b>文件上传状态:</b><br/>");
			if (fileUploadStats.getBytesRead() != fileUploadStats
					.getTotalSize()) {
				response.getWriter().println(
						"<div class=\"prog-border\"><div class=\"prog-bar\" style=\"width: "
								+ percentComplete + "%;\"></div></div>");
				response.getWriter().println(
						"已上传: " + bytesProcessed + "bytes 总大小:" + sizeTotal
								+ " bytes (" + percentComplete + "%) "
								+ (long) Math.round(uploadRate / 1024)
								+ " Kbs <br/>");
				response.getWriter().println(
						"已用时间: " + formatTime(timeInSeconds) + " 总共所需时间 "
								+ formatTime(estimatedRuntime) + " "
								+ formatTime(estimatedRuntime - timeInSeconds)
								+ " 剩余 <br/>");
			} else {
				response.getWriter().println(
						"共上传: " + bytesProcessed + " bytes 总大小:" + sizeTotal
								+ " bytes<br/>");
				response.getWriter().println("文件上传完毕.<br/>");
			}
		}
		// 如果文件已经上传完毕
		if (fileUploadStats != null
				&& fileUploadStats.getBytesRead() == fileUploadStats
						.getTotalSize()) {
			response.getWriter().println("<b>Upload complete.</b>");
		}
	}

	private void sendCompleteResponse(HttpServletResponse response,
			String message) {
		try {
			if (message == null) {
				response
						.getOutputStream()
						.print(
								"<html><head><script type='text/ javascript'> function killUpdate() { window.parent.killUpdate(''); }</script></head><body onload='killUpdate()'></body></html>");
			} else {
				response
						.getOutputStream()
						.print(
								"<html><meta http-equiv=\"content-type\" content=\"text/html;charset=utf-8\"><head><script type='text/ javascript'>function killUpdate() { window.parent.killUpdate('"
										+ message
										+ "'); }</script></head><body onload='killUpdate()'></body></html>");
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	private String formatTime(double timeInSeconds) {
		long seconds = (long) Math.floor(timeInSeconds);
		long minutes = (long) Math.floor(timeInSeconds / 60.0);
		long hours = (long) Math.floor(minutes / 60.0);

		if (hours != 0) {
			return hours + "hours " + (minutes % 60) + "minutes "
					+ (seconds % 60) + "seconds";
		} else if (minutes % 60 != 0) {
			return (minutes % 60) + "minutes " + (seconds % 60) + "seconds";
		} else {
			return (seconds % 60) + " seconds";
		}
	}
}
